//
//  KTHttpUtils.m
//  BoWuGuan
//
//  Created by 梁尚嘉 on 2016/10/31.
//  Copyright © 2016年 KT. All rights reserved.
//

#import "KTHttpUtils.h"
#import <AFNetworking.h>
#import "Notification.h"
#import "Storage.h"
//#import "HUD_Utils.h"
//#import <JPUSHService.h>
#import "Navigator.h"
#import "MainConfigure.h"
NSString *const OM_NOTIFICATION_KEY_LOGIN_SUCCESS = @"OM_NOTIFICATION_LOGIN_SUCCESS";
NSString *const OM_NOTIFICATION_KEY_LOGOUT_SUCCESS = @"OM_NOTIFICATION_LOGOUT_SUCCESS";
#define kServerDebugDomain      @"http://test.omengo.com"///*@"http://192.168.9.33:8080"*/@"http://192.168.9.43:8086"
#define kServerDebugDomainKey   @"kServerDebugDomain_key"
#define kServerProductDomain    @"https://www.omengo.com"//@"http://www.omengo.com"


//http://192.168.9.69:8080/api/app/newIndex

#define HTTPManager [KTHttpUtils manager]

#define IS_DEBUGING_KEY @"is_debuging"
#define UN_STATABLE_NET_MESSAGE @"当前网络环境较差"

#define kTimeoutInterval 10.f
#define TOKEN_KEY @"Authorization"

@interface KTHTTPSessionManager : AFHTTPSessionManager
@end
@implementation KTHTTPSessionManager

@end



@implementation KTHttpUtils
//static AFHTTPSessionManager *manager = nil;
static KTHttpUtils *_shareInstace = nil;
AFNetworkReachabilityManager *_reachabilityManager = nil;
NSString * _serverDomain = nil;
+ (instancetype)shareInstance
{
    static dispatch_once_t onceToken;

    dispatch_once(&onceToken, ^{
        if (_shareInstace == nil) {
            HTTPManager.responseSerializer = [AFHTTPResponseSerializer serializer];
            [HTTPManager.requestSerializer willChangeValueForKey:@"timeoutInterval"];
            HTTPManager.requestSerializer.timeoutInterval = kTimeoutInterval;
            HTTPManager.responseSerializer.acceptableContentTypes = [NSSet setWithObject:@"application/json"];
            [HTTPManager.requestSerializer didChangeValueForKey:@"timeoutInterval"];
            //设置请求url地址前缀
            [self reloadServerDomain];
            _shareInstace = [[self alloc] init];
        }
    });

    return _shareInstace;
}

/**
 *  清除cookies 删除登录状态
 */
+ (void)clearCookies
{
    NSHTTPCookieStorage *cookieJar = [NSHTTPCookieStorage sharedHTTPCookieStorage];
    //    我们这里获取到了这个单例，把在线的Domain作为参数使用cookiesForURL:方法，就可以得到一个数组，这里拿到数组就可以归档实现保存本地。
    //    清除cookie的话，在遍历数组的时候使用deleteCookie:的方法，就可以把cookie全部清掉，实现我们想要的清除cookie的操作。
    NSArray *cookies = [cookieJar cookiesForURL: [NSURL URLWithString:[_serverDomain stringByReplacingOccurrencesOfString:@"/api/" withString:@""]]];

    for (NSHTTPCookie *cookie in cookies) {
        NSLog(@"cookieName: %@", [cookie name]);
        [cookieJar deleteCookie:cookie];
    }
    NSLog(@"cookies: %@", cookies);

}


+ (BOOL)is_WIFI_reachable
{
    return _reachabilityManager.reachableViaWiFi;
}

+ (BOOL)is_WWAN_reachable
{
    return _reachabilityManager.reachableViaWWAN;
}

//监测网络
+ (void)AFNetworkStatusObserve{

    _reachabilityManager = [AFNetworkReachabilityManager sharedManager];
    [_reachabilityManager startMonitoring];
    [_reachabilityManager setReachabilityStatusChangeBlock:^(AFNetworkReachabilityStatus status) {
        switch (status)
        {
            case AFNetworkReachabilityStatusUnknown:

                break;
            case AFNetworkReachabilityStatusNotReachable:

                break;
            case AFNetworkReachabilityStatusReachableViaWWAN:

                break;
            case AFNetworkReachabilityStatusReachableViaWiFi:

                break;
        }
    }] ;
}


+ (void)reloadServerDomain
{
    NSNumber *value = SMUserDefaultGet(IS_DEBUGING_KEY);
    BOOL isDebug = [value boolValue];
    _serverDomain = !isDebug ?  kServerProductDomain :
    ({
        NSString *domain = SMUserDefaultGet(kServerDebugDomainKey);
        domain.length ? domain : kServerDebugDomain;
    });
    _serverDomain = [_serverDomain stringByAppendingString:@"/api/"];
    [self AFNetworkStatusObserve];
    //    ![Storage isLogin]?:[self autoLoginOnResult:nil];
}

+ (NSString *)currentDomain
{
    return _serverDomain;
}

+ (NSString *)currentDomainPrefix
{
    return [_serverDomain stringByReplacingOccurrencesOfString:@"/api/" withString:@""];
}


+ (void)setDebugDomain:(NSString *)domain
{
    SMUserDefaultSet(kServerDebugDomainKey, domain?domain:@"");
    [self reloadServerDomain];
}


+ (NSString *)currentMode
{
    NSNumber *value = SMUserDefaultGet(IS_DEBUGING_KEY) ;
    BOOL isDebug = [value boolValue];
    return !isDebug ? @"生产环境" : @"开发环境";
}


+ (void)startRunning
{
    [self shareInstance];
}


+ (void)setServerMode:(KTServerMode)mode
{
    if (mode == KTServerDebugMode) {
        SMUserDefaultSet(IS_DEBUGING_KEY, @(YES));

    }else if (mode == KTServerProductMode) {
        SMUserDefaultSet(IS_DEBUGING_KEY, @(NO));
    }
    [self reloadServerDomain];
}

+ (BOOL)isDebug
{
    return [SMUserDefaultGet(IS_DEBUGING_KEY) boolValue];
}


+ (KTURLSessionTask *)GET:(NSString *)URLString
               completion:(KTHttpUtilCompletion)completion
{
    return [self GET:URLString
          parameters:nil
            progress:nil
          completion:completion];
}


+ (KTURLSessionTask *)GET:(NSString *)URLString
               parameters:(id)parameters
                 progress:(KTHttpUtilProgress)progress
               completion:(KTHttpUtilCompletion)completion
{

    return [self GET:URLString
          parameters:parameters
           needCache:YES
            progress:progress
          completion:completion];
}

+ (KTURLSessionTask *)GET_NOCACHE:URLString
                       parameters:(id)parameters
                         progress:(KTHttpUtilProgress)progress
                       completion:(KTHttpUtilCompletion)completion
{
    return [self GET:URLString
          parameters:parameters
           needCache:NO
            progress:progress
          completion:completion];
}

+ (KTURLSessionTask *)GET:(NSString *)URLString
               parameters:(id)parameters
                needCache:(BOOL)needCache
                 progress:(KTHttpUtilProgress)progress
               completion:(KTHttpUtilCompletion)completion
{
    return [self GET:URLString
          parameters:parameters
           needCache:needCache
           needToken:YES
            progress:progress
          completion:completion];
}

+ (KTURLSessionTask *)GET:(NSString *)URLString
               parameters:(id)parameters
                needCache:(BOOL)needCache
                needToken:(BOOL)needToken
                 progress:(KTHttpUtilProgress)progress
               completion:(KTHttpUtilCompletion)completion
{
    NSString *finalUrl = [self.currentDomain stringByAppendingString:URLString];
    parameters = needToken?[self parametersWithToken:parameters]:parameters;
    if ([parameters isKindOfClass:[NSDictionary class]]) {

        NSUInteger index = 0;
        NSArray *allKeys = [parameters allKeys];
        for (NSString *key in allKeys) {
            finalUrl = [finalUrl stringByAppendingString: index ? @"&":@"?"];
            finalUrl = [finalUrl stringByAppendingString:[NSString stringWithFormat:@"%@=%@",key,parameters[key]]];
            index++;
        }
    }
    finalUrl = [finalUrl stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];

//    if ((!_reachabilityManager.isReachable && needCache)) {
//        progress = nil;
//
//        id cacheData = [Storage getCacheByGetMethodWithUrl:finalUrl];
//        if (cacheData) {
//            !completion ?: completion(cacheData,YES,@"已读取本地缓存");
//        }else if (!_reachabilityManager.isReachable){
//            !completion ?: completion(nil,NO,@"无法连接服务器");
//            return nil;
//        }
//    }

    return KTURLSessionTaskMake([HTTPManager GET:finalUrl
                                      parameters:nil
                                        progress:^(NSProgress * _Nonnull downloadProgress) {
                                            progress ? progress(downloadProgress) : NULL;

                                        }
                                         success:^(NSURLSessionTask *task, id responseObject) {
                                             [self handleTask:task
                                            andResponseObject:responseObject
                                                        isGET:YES
                                                     cacheUrl: needCache ? finalUrl : nil
                                               withCompletion:completion
                                               onReverseBlock:^(BOOL isReverse) {
                                                   [self autoLoginOnResult:^(BOOL isSuccess, NSString *message) {
                                                       if (isSuccess) {
                                                           [self GET:URLString
                                                          parameters:parameters
                                                            progress:progress
                                                          completion:completion];

                                                       }else {
                                                           completion(nil,NO,message);
                                                       }
                                                   }];
                                               }];
                                         }
                                         failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
                                             //(网络不通的情况)请求失败的处理
                                             if (needCache)
                                             {   //有则返回缓存
                                                 id cacheData = [Storage getCacheByGetMethodWithUrl:finalUrl];
                                                 if (cacheData)
                                                 {
                                                     if ([cacheData isKindOfClass:[NSDictionary class]]) {
                                                         !completion ?: completion(cacheData,YES,@"已读取本地缓存");
                                                     }else {
                                                         !completion ?: completion(nil,NO,UN_STATABLE_NET_MESSAGE);
                                                     }

                                                 }
                                                 else
                                                 {
                                                     !completion ?: completion(nil,NO,UN_STATABLE_NET_MESSAGE);
                                                 }
                                             }
                                             else
                                             {
                                                 completion(nil,NO,UN_STATABLE_NET_MESSAGE);

                                             }
                                             NSHTTPURLResponse *response = (id)task.response;
                                             NSLog(@"task= %@",  [NSHTTPURLResponse localizedStringForStatusCode:response.statusCode]);

                                         }]);
}


+ (NSDictionary *)parametersWithToken:(NSDictionary *)parameters
{

    NSMutableDictionary *dictionary = [parameters?:@{} mutableCopy];
    NSString *token = SMUserDefaultGet(TOKEN_KEY)?:@"123456";
    ![Storage isLogin]?:[dictionary setObject:token forKey:@"token"];
    return dictionary;
}


+ (KTURLSessionTask *)POST:(NSString *)URLString
                parameters:(NSDictionary *)parameters
                 needToken:(BOOL)needToken
                  progress:(KTHttpUtilProgress)progress
                completion:(KTHttpUtilCompletion)completion
{
    return KTURLSessionTaskMake([HTTPManager POST: [self urlFactoryWithPix:URLString]
                                       parameters:needToken?[self parametersWithToken:parameters]:parameters
                                         progress:^(NSProgress * _Nonnull uploadProgress) {
                                             progress ? progress(uploadProgress) : NULL;

                                         }
                                          success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {

                                              [self handleTask:task
                                             andResponseObject:responseObject
                                                withCompletion:completion
                                                onReverseBlock:^(BOOL isReverse) {

                                                    [self autoLoginOnResult:^(BOOL isSuccess, NSString *message) {
                                                        if (isSuccess) {

                                                            [self POST:URLString
                                                            parameters:parameters
                                                              progress:progress
                                                            completion:completion ];
                                                        }else {

                                                            completion(nil,NO,message);
                                                        }
                                                    }];
                                                }];

                                          }
                                          failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {

                                              //(网络不通的情况)请求失败的处理
                                              NSLog(@"task= %li",  (long)((NSHTTPURLResponse *)task.response).statusCode);
                                              completion(nil,NO,UN_STATABLE_NET_MESSAGE);

                                          }]);
}

+ (KTURLSessionTask *)POST:(NSString *)URLString
                parameters:(NSDictionary *)parameters
                  progress:(KTHttpUtilProgress)progress
                completion:(KTHttpUtilCompletion)completion
{

    return [self POST:URLString
           parameters:parameters
            needToken:TRUE
             progress:progress
           completion:completion];
}


+ (KTURLSessionTask *)DELETE:(NSString *)URLString
                  parameters:(id)parameters
                  completion:(KTHttpUtilCompletion)completion
{

    return KTURLSessionTaskMake([HTTPManager DELETE:[self urlFactoryWithPix:URLString]
                                         parameters:parameters
                                            success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {

                                                [self handleTask:task
                                               andResponseObject:responseObject
                                                  withCompletion:completion
                                                  onReverseBlock:^(BOOL isReverse) {

                                                      [self autoLoginOnResult:^(BOOL isSuccess, NSString *message) {
                                                          if (isSuccess) {
                                                              [self DELETE:URLString
                                                                parameters:parameters
                                                                completion:completion];
                                                          }else {
                                                              completion(nil,NO,message);

                                                          }
                                                      }];
                                                  }];

                                            }
                                            failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
                                                //(网络不通的情况)请求失败的处理
                                                completion(nil,NO,UN_STATABLE_NET_MESSAGE);
                                                NSLog(@"task= %li",  (long)((NSHTTPURLResponse *)task.response).statusCode);

                                            }]);
}


+ (void)loginWithUserName:(NSString *)username
                 password:(NSString *)password
                 onResult:(KTHttpUtilLoginResult)result
{

    //    account/loginV2
    NSString *url = [NSString stringWithFormat:@"account/login.jhtml?username=%@&smsCode=%@",username,password];
    [KTHttpUtils GET:url
          parameters:nil
           needCache:NO
           needToken:NO
            progress:nil
          completion:^(id responseObject, BOOL isSuccess, NSString *message) {

        if (isSuccess) {
            KTSystemStorageSingleton.username       = username;
            SMUserDefaultSet(TOKEN_KEY, responseObject[@"token"]);
            OMAccount *account = [OMAccount mj_objectWithKeyValues:responseObject[@"info"]];
            account.avatar = [responseObject[OMImagePrefix] stringByAppendingString:account.avatar];
            KTSystemStorageSingleton.account = account;

            [Storage setLogin:@(YES)];
            !result ?: result(YES,message);
        }
        else {
            !result ?: result(NO,message);
        }
        NSLog(@"登录%@",isSuccess?@"成功":@"失败");
    }];

}

- (void)aliasSetHandle:(id)response
{

}

+ (void)autoLoginOnResult:(KTHttpUtilLoginResult)result
{
    if ([Storage isLogin]) {
//        [Storage setLogin:NO];
        [Navigator showLoginViewWithoutLogin];
        !result ?: result(NO,@"登录状态已失效,请登录");
    }
}

//请求工具类设置
+ (KTHTTPSessionManager *)manager
{
    KTHTTPSessionManager *manager = [KTHTTPSessionManager manager];

    // 设置请求头
    [manager.requestSerializer willChangeValueForKey:@"timeoutInterval"];
    manager.requestSerializer.timeoutInterval = kTimeoutInterval;
    [manager.requestSerializer setValue:@"application/x-www-form-urlencoded; charset=utf-8" forHTTPHeaderField:@"Content-Type"];
    //    [manager.requestSerializer setValue:token forHTTPHeaderField:TOKEN_KEY];
    [manager.requestSerializer didChangeValueForKey:@"timeoutInterval"];

    //设置响应头
    NSNumber *value = SMUserDefaultGet(IS_DEBUGING_KEY) ;
    BOOL isDebug = [value boolValue];
    if (!isDebug) {
        manager.responseSerializer = [AFHTTPResponseSerializer serializer];
        manager.securityPolicy.validatesDomainName = NO; // 关键语句1
        manager.securityPolicy.allowInvalidCertificates = YES; // 关键语句2
    }

    return manager;
}



/**
 用utf8编码请求字段

 @param parameters <#parameters description#>
 @return <#return value description#>
 */
+ (NSDictionary *) utfEncodeParameter:(NSDictionary *)parameters
{
    return ({
        NSMutableDictionary *mu_parameters = [parameters mutableCopy];
        for (id<NSCopying> key in parameters.allKeys) {
            id value = parameters[key];
            if ([value isKindOfClass:[NSString class]]) {
                [mu_parameters setObject:[parameters[key] stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding] forKey:key];
            }else {
                [mu_parameters setObject:parameters[key] forKey:key];
            }
        }
        mu_parameters;
    });
}



/**
 图片上传

 @param pix 图片后缀名
 @param parameters 字段键值对
 @param fileURLs 文件url数组
 @param progress 进度block
 @param completion 回调block
 @return KTURLSessionTask实例
 */
+ (KTURLSessionTask *)UPLOADImage:(NSString *)pix
                       parameters:(NSDictionary *)parameters
                         fileURLs:(NSArray<NSURL *> *)fileURLs
                         progress:(KTHttpUtilProgress)progress
                       completion:(KTHttpUtilCompletion)completion
{

    return
    KTURLSessionTaskMake(([HTTPManager POST:[self urlFactoryWithPix:pix] parameters:[self utfEncodeParameter:parameters] constructingBodyWithBlock:^(id<AFMultipartFormData>  _Nonnull formData) {

        for (NSUInteger index = 0; index< fileURLs.count; index++) {
            NSString *file = [NSString stringWithFormat:@"file_%lu",(unsigned long)index];
            [formData appendPartWithFileURL:fileURLs[index]
                                       name:file
                                   fileName:[NSString stringWithFormat:@"%@.jpg",[NSUUID UUID].UUIDString]
                                   mimeType:@"image/jpeg"
                                      error:nil];
        }

    } progress:^(NSProgress * _Nonnull uploadProgress) {

        dispatch_async(dispatch_get_main_queue(), ^{
            !progress ?: progress(uploadProgress);
        });

    } success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {

        [self handleTask:task
       andResponseObject:responseObject
          withCompletion:completion
          onReverseBlock:^(BOOL isReverse) {
              [self autoLoginOnResult:^(BOOL isSuccess, NSString *message) {

                  if (isSuccess) {
                      [self UPLOADImage:pix parameters:parameters fileURLs:fileURLs progress:progress completion:completion];

                  }else {
                      completion(nil,NO,message);

                  }
              }];
          }];

    } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
        //(网络不通的情况)请求失败的处理
        NSLog(@"task= %li",  (long)((NSHTTPURLResponse *)task.response).statusCode);
        completion(nil,NO,UN_STATABLE_NET_MESSAGE);

    }]));

}



//统一处理请求反馈
+ (void)handleTask:(NSURLSessionTask *)task
 andResponseObject:(id)responseObject
    withCompletion:(KTHttpUtilCompletion)completion
    onReverseBlock:(KTHttpUtilReverse)reverse
{
    [self handleTask:task
   andResponseObject:responseObject
               isGET:NO
            cacheUrl:nil
      withCompletion:completion
      onReverseBlock:reverse];
}

//统一处理请求反馈
+ (void)handleTask:(NSURLSessionTask *)task
 andResponseObject:(id)responseObject
             isGET:(BOOL)isGET
          cacheUrl:(NSString *)cacheUrl
    withCompletion:(KTHttpUtilCompletion)completion
    onReverseBlock:(KTHttpUtilReverse)reverse
{
    if (!responseObject) {
        completion(nil,YES,@"无数据");
        reverse = nil;
    }else {

        NSDictionary *dict = [responseObject isKindOfClass:[NSDictionary class]] ? responseObject : [NSJSONSerialization JSONObjectWithData:responseObject options:NSJSONReadingMutableLeaves error:nil];
        NSString *message  = dict[@"message"];

        if ([dict isKindOfClass:[NSDictionary class]] && [dict[@"code"] integerValue] == 1) //request successfully
        {
            //判断与缓存TOKEN
            [self cacheCookiesWithTask:task];
            [[NSURLCache sharedURLCache] removeAllCachedResponses];

            //保存缓存
            if (isGET&&cacheUrl) {
                [Storage saveCacheGetMethodDataWithUrl:cacheUrl withData:dict];
            }

            NSString *responseString = [[dict mj_JSONString] stringByReplacingOccurrencesOfString:@"null" withString:@"\"\""];
            completion(dict,YES,message);
            reverse = nil;
            
        }else {
            
            //Token失效
            if ([dict[@"code"]integerValue] == 422) {
                reverse(YES);
            }else {
                //(与后台交互的情况)请求失败的处理
                completion(nil,NO,message ? message : @"网络请求超时");
                reverse = nil;
            }
        }
    }
}


//判断与缓存TOKEN
+ (void)cacheCookiesWithTask:(NSURLSessionTask *)task
{
    NSHTTPURLResponse *response = (NSHTTPURLResponse *) task.response;
    NSString *string =response.allHeaderFields[@"Set-Cookie"];
    NSRange range = [string rangeOfString:@"rememberMe" options:NSBackwardsSearch];//匹配得到的下标
    if (range.length) {
        string = [string substringFromIndex:range.location];
        [Storage saveAuthorizationToken:string];
    }
}


+ (NSString *)urlFactoryWithPix:(NSString *)pix
{
    NSString *finalUrl = [self.currentDomain stringByAppendingString:pix];
    finalUrl = [finalUrl stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
    return finalUrl;
}


+ (NSString *)imageURLWithPix:(NSString *)pix
{
    return [[_serverDomain stringByReplacingOccurrencesOfString:@"/api/" withString:@""] stringByAppendingString:pix];
}



@end
